﻿using System;
using System.Data;
using System.DirectoryServices;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

namespace Vision.Core.ActivityComponents.ActiveDirectory
{
    /// <summary>
    /// 
    /// </summary>
    static class ActiveDirectoryHelper
    {

        #region [ FindUserByLogonName ]
        /// <summary>
        /// 
        /// </summary>
        /// <param name="logonName"></param>
        /// <returns></returns>
        public static DirectoryEntry FindUserByLogonName(string logonName)
        {
            return GetDirectoryEntry("(&(objectClass=Person)(sAMAccountName=" + logonName + "))");
        }
        #endregion

        #region [ FindGroupByAlias ]
        /// <summary>
        /// 
        /// </summary>
        /// <param name="groupAlias"></param>
        /// <returns></returns>
        public static DirectoryEntry FindGroupByAlias(string groupAlias)
        {
            return GetDirectoryEntry("(&(objectClass=Group)(sAMAccountName=" + groupAlias + "))");
        }
        #endregion

        #region [ FindUsersByFirstName ]
        /// <summary>
        /// Gets a <see cref="SearchResultCollection"/> of users by first name.
        /// </summary>
        /// <param name="firstName"></param>
        /// <returns></returns>
        public static SearchResultCollection FindUsersByFirstName(string firstName)
        {
            return GetDirectoryEntries("(&(objectClass=Person)(givenName=" + firstName + "*))");
        }
        #endregion

        #region [ FindUsersByLastName ]
        /// <summary>
        /// Gets a <see cref="SearchResultCollection"/> of users by last name.
        /// </summary>
        /// <param name="lastName"></param>
        /// <returns></returns>
        public static SearchResultCollection FindUsersByLastName(string lastName)
        {
            return GetDirectoryEntries("(&(objectClass=Person)(sn=" + lastName + "*))");
        }
        #endregion

        #region [ FindDirectReports ]
        /// <summary>
        /// Gets a <see cref="SearchResultCollection"/> of users who are direct reports of the input user.
        /// </summary>
        /// <param name="logonName"></param>
        /// <returns></returns>
        public static SearchResultCollection FindDirectReports(string logonName)
        {
            try
            {
                DirectoryEntry manager = FindUserByLogonName(logonName);
                return GetDirectoryEntries("(&(objectClass=Person)(manager=" + manager.Path + "))");
            }
            catch
            {
                return null;
            }
        }
        #endregion

        #region [ GetEntryValue ]
        public static T GetEntryValue<T>(DirectoryEntry entry, string propertyName)
        {
            return (T)GetEntryValue(entry, propertyName);
        }

        public static object GetEntryValue(DirectoryEntry entry, string propertyName)
        {
            if (entry == null)
                throw new ArgumentNullException("entry");

            if (!entry.Properties.Contains(propertyName))
                throw new ArgumentException("The property " + propertyName + " cannot be found.", "propertyName");

            return entry.Properties[propertyName].Value;
        }
        #endregion

        #region [ GetDirectoryEntry ]
        /// <summary>
        /// Gets a <see cref="DirectoryEntry"/> for the input filter string.
        /// </summary>
        /// <param name="filterString"></param>
        /// <returns>
        /// This method returns one <see cref="SearchResult"/> or null if no results are found.
        /// </returns>
        public static DirectoryEntry GetDirectoryEntry(string filterString)
        {
            using (DirectorySearcher searcher = new DirectorySearcher(filterString))
            {

                SearchResult result = searcher.FindOne();

                if (result == null)
                    throw new Exception("User not found");

                return result.GetDirectoryEntry();
            }
        }
        #endregion

        #region [ GetDirectoryEntries ]
        private static SearchResultCollection GetDirectoryEntries(string filterString)
        {
            using (DirectorySearcher searcher = new DirectorySearcher(filterString))
            {

                SearchResultCollection results = searcher.FindAll();

                if (results.Count == 0)
                    throw new ApplicationException("No results found. filterString=" + filterString);

                return results;
            }
        }
        #endregion

        #region [ SetEntryValue ]
        public static void SetEntryValue(DirectoryEntry entry, string ldapPropertyName, object ldapPropertyValue)
        {
            entry.Invoke("Put", ldapPropertyName, ldapPropertyValue);
            entry.Invoke("SetInfo");
        }
        #endregion
    } 
}
